package com.sc.test.recyclerview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.sc.test.R;

/**
 * Created by Shen Chao on 2018-01-22-022 上午 10:21.
 */

public class StickyRecyclerView extends RecyclerView {
    private int lineHeight, titleHeight;
    private int lineColor, titleColor, titleTextColor;

    public StickyRecyclerView(Context context) {
        this(context, null);
    }

    public StickyRecyclerView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public StickyRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.StickyRecyclerView);
        // 分割线的高度
        lineHeight = array.getDimensionPixelOffset(R.styleable.StickyRecyclerView_dividerHeight, 1);
        // 分栏的高度
        titleHeight = array.getDimensionPixelOffset(R.styleable.StickyRecyclerView_titleHeight, dip2px(context, 35));
        // 分割线颜色
        lineColor = array.getColor(R.styleable.StickyRecyclerView_dividerColor, Color.LTGRAY);
        // 分栏背景色
        titleColor = array.getColor(R.styleable.StickyRecyclerView_titleColor, Color.LTGRAY);
        // 分栏文字颜色
        titleTextColor = array.getColor(R.styleable.StickyRecyclerView_titleTextColor, Color.BLUE);
        array.recycle();
        setLayoutManager(new LinearLayoutManager(context));
    }

    public void setAdapter(@NonNull StickyAdapter stickyAdapter) {
        addItemDecoration(new StickyDivider(stickyAdapter));
        super.setAdapter(stickyAdapter);
    }

    private class StickyDivider extends ItemDecoration {
        private StickyAdapter adapter;
        private Paint paint;

        StickyDivider(@NonNull StickyAdapter adapter) {
            super();
            this.adapter = adapter;
            paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint.setStyle(Paint.Style.FILL);
            paint.setTextSize(titleHeight * 0.5f);
        }

        /**
         * 计算分割线，是title还是普通分割线
         *
         * @param outRect
         * @param view
         * @param parent
         * @param state
         */
        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) {
            super.getItemOffsets(outRect, view, parent, state);
            if (!adapter.needTitle(((LayoutParams) view.getLayoutParams()).getViewLayoutPosition())) {
                outRect.top = lineHeight;
            } else {
                outRect.top = titleHeight;
            }
        }

        /**
         * 顶部绘制分割线
         *
         * @param c
         * @param parent
         * @param state
         */
        @Override
        public void onDraw(Canvas c, RecyclerView parent, State state) {
            super.onDraw(c, parent, state);
            int left = parent.getPaddingLeft();
            int right = parent.getMeasuredWidth() - parent.getPaddingRight();
            final int childCount = parent.getChildCount();
            for (int i = 0; i < childCount; i++) {
                final View child = parent.getChildAt(i);
                int position = ((LayoutParams) child.getLayoutParams()).getViewLayoutPosition();
                int bottom = child.getTop() - ((LayoutParams) child.getLayoutParams()).topMargin;
                if (!adapter.needTitle(position)) {
                    // 画分割线
                    int top = bottom - lineHeight;
                    paint.setColor(lineColor);
                    c.drawRect(left, top, right, bottom, paint);
                } else {
                    //画title
                    int top = bottom - titleHeight;
                    paint.setColor(titleColor);
                    c.drawRect(left, top, right, bottom, paint);
                    drawText(c, adapter.getItemViewTitle(position), left + titleHeight * 0.25f, bottom - titleHeight * 0.25f);
                }
            }
        }

        private void drawText(Canvas c, String itemViewTitle, float x, float y) {
            if (!TextUtils.isEmpty(itemViewTitle)) {
                paint.setColor(titleTextColor);
                //paint.getTextBounds(itemViewTitle, 0, itemViewTitle.length(), mBounds);
                c.drawText(itemViewTitle, x, y, paint);
            }
        }

        /**
         * 在item上绘制悬停view
         *
         * @param c
         * @param parent
         * @param state
         */
        @Override
        public void onDrawOver(Canvas c, RecyclerView parent, State state) {
            super.onDrawOver(c, parent, state);
            // 悬停title
            int left = parent.getPaddingLeft();
            int right = parent.getMeasuredWidth() - parent.getPaddingRight();
            int top = parent.getPaddingTop();
            int bottom = top + titleHeight;
            paint.setColor(titleColor);
            c.drawRect(left, top, right, bottom, paint);
            int pos = ((LinearLayoutManager) (parent.getLayoutManager())).findFirstVisibleItemPosition();
            drawText(c, adapter.getItemViewTitle(pos), left + titleHeight * 0.25f, bottom - titleHeight * 0.25f);
        }
    }

    public static abstract class StickyAdapter extends Adapter {
        // 获取当前 item 的标题
        public abstract String getItemViewTitle(int position);

        //如果标题和前边一样就不要绘制
        boolean needTitle(int position) {
            return position > -1 && (position == 0 || !getItemViewTitle(position).equals(getItemViewTitle(position - 1)));
        }
    }

    /**
     * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
     */
    public static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }
}
